#include <YuvIoctl.h>

/**/
struct YuvIoImpl_NV12S
{
    YuvIoT base;
    char *file;
    uint8_t *y;
    uint8_t *uv;
    int picW;
    int picH;
    int datW;
    int datH;
};

static uint8_t __NV12readY(YuvIoT *yuv, int x, int y)
{
    struct YuvIoImpl_NV12S *impl;
    uint8_t ret;
    
    impl = ZContainerOf(yuv, struct YuvIoImpl_NV12S, base);
    
    Z_ASSERT(x < impl->picW && y < impl->picH);

    ret = impl->y[y*impl->datW + x];
    return ret;
}

static uint8_t __NV12readU(YuvIoT *yuv, int x, int y)
{
    struct YuvIoImpl_NV12S *impl;
    uint8_t ret;
    
    impl = ZContainerOf(yuv, struct YuvIoImpl_NV12S, base);
    
    Z_ASSERT(x < impl->picW && y < impl->picH);

    ret = impl->uv[(y*impl->datW + x)/2];
    return ret;
}

static uint8_t __NV12readV(YuvIoT *yuv, int x, int y)
{
    struct YuvIoImpl_NV12S *impl;
    uint8_t ret;
    
    impl = ZContainerOf(yuv, struct YuvIoImpl_NV12S, base);
    
    Z_ASSERT(x < impl->picW && y < impl->picH);

    ret = impl->uv[(y*impl->datW + x)/2 + 1];
    return ret;
}

struct YuvIoOpsS yuvOps_NV12 =
{
    .readY = __NV12readY,
    .readU = __NV12readU,
    .readV = __NV12readV
};

YuvIoT *YuvIoInstance_NV12(char *file, int picW, int picH, int datW, int datH)
{
    FILE *stream;
    int ret;
    struct YuvIoImpl_NV21S *impl;
    
    impl = malloc(sizeof(*impl));
    impl->base.ops = &yuvOps_NV21;
    impl->file = strdup(file);
    impl->picW = picW;
    impl->picH = picH;
    impl->datW = datW;
    impl->datH = datH;
    
    stream = fopen(file);
    Z_ASSERT(stream);

    impl->y = malloc(datW * datH);
    ret = fread(impl->y, datW, datH, stream);
    Z_ASSERT(ret == datH);

    impl->uv = malloc((datW * datH)/2);
    ret = fread(impl->uv, datW/2, datH);
    Z_ASSERT(ret = datH);

    return 
}

